""" Simple Resource Management.

    This is the most simplistic resource manager I could come up with.
    There are virtually no frills at all.
    
    WARNING: This is NOT to be used in conjunction with other resource
    managers!
"""

import os
from weakref import WeakValueDictionary

class Mgr(object):
    """ Manages the loading of resources as needed. """
    def __init__(self):
        self._fnameres = WeakValueDictionary() # Filename -> Res. Obj.
        self._cwd = os.path.curdir # Default cwd
        self._metadata = {} # Filenamames -> Metadata Dict.
        self._extloader = {} # Extension -> Loader Func.
        self._extalias = {} # Extension -> Alias
    
    def set_loader(self,ext,loader):
        """ Creates or replaces a new loader for a file extension
        
            When a file with the given extension must be loaded the
            filename will be passed to the given loader along with
            whatever metadata is attached to the filename and the
            value returned will be passed back to the caller. The
            metadata will be passed by keyword.
            
            Instead of passing an extension you may pass a whole
            sequence of extensions. Files with any of the extensions
            will be treated the same as files with the first.
            
            The manager does not pay attention to the case of file
            extensions. However, the case of the extension is preserved
            when passed to the loader.
        """
        self._extloader[ext.lower()] = loader
    
    def remove_loader(self,ext):
        """ Removes a loader for a file extension.
            The case is ignored. After calling this the Mgr will not be
            able to load files with the given extension.
        """
        del self._extloader[ext.lower()]
    
    def get_cwd(self):
        """ Return the current current working directory.
        
            This is not the current directory of the entire program.
            This "CWD" is only used when a colon (:) is used at the
            beginning of a filename passed to get().
            By default the cwd is the currentdir symbol (ie. '.' on
            Windows and Unix, etc.)
        """
        return self._cwd
    
    def set_cwd(self,cwd=os.path.curdir):
        """ Set the current working directory.
            See the note at get_cwd().
        """
        self._cwd = cwd
    
    def get(self,fname):
        """ Loads the file with the given name.
        
            A colon (:) at the beginning of
            the filename will be interpreted as the Mgr's cwd.
            
            In any case, the absolute filename of the resource is stored
            internally and if a string that equates to the same absolute
            filename is given the existing copy is used instead.
            
            The case of the extension on the filename is ignored when
            used to determine which loader to use.
        """
        # Interpret colon at the beginning of the filename.
        if fname.startswith(':'):
            fname = os.path.join(self._cwd, fname[1:])
        # Get absolute path to the filename.
        absfname = os.path.abspath(fname)
        # If the resource is already loaded use the existing object.
        if absfname in self._fnameres:
            return self._fnameres[absfname]
        # If the resource is NOT already loaded, load it.
        else:
            # Get the extension
            root, ext = os.path.splitext(fname)
            ext = ext.lower()
            # Call the loader
            self._fnameres[absfname] = r = self._extloader[ext](fname)
            return r
            